package com.sgb.contract.base;

import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.sgb.contract.BR;
import com.sgb.contract.R;
import com.sgb.contract.base.viewmodel.BaseViewModel;
import com.sgb.contract.databinding.ContractFragmentBaseBinding;
import com.sgb.contract.databinding.ViewLoadErrorBinding;
import com.sgb.contract.databinding.ViewNoDataBinding;
import com.sgb.contract.databinding.ViewNoNetworkBinding;
import com.sgb.contract.utils.StringUtils;
import com.sgb.contract.view.widget.TagBuilder;
import com.swgk.core.dialog.DialogHelper;
import com.swgk.core.dialog.RoundDialog;


/**
 * Fragment的基类
 *
 * @param <DB> data binding
 * @param <VM> view model
 * @author cyj
 */
public abstract class BaseFragment<DB extends ViewDataBinding, VM extends BaseViewModel>
        extends Fragment {

    protected DB mDataBinding;
    protected VM mViewModel;
    private int variableId = 0;
    private ContractFragmentBaseBinding mFragmentBaseBinding;
    private ViewLoadErrorBinding mViewLoadErrorBinding;
    private ViewNoNetworkBinding mViewNoNetworkBinding;
    private ViewNoDataBinding mViewNoDataBinding;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (null != getArguments()) {
            handleBundle(getArguments());
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mFragmentBaseBinding = DataBindingUtil.inflate(inflater, R.layout.contract_fragment_base, container, false);
        mDataBinding = DataBindingUtil.inflate(inflater, getLayoutResId(), mFragmentBaseBinding.flContentContainer, true);

        initViewModel();
        baseInitViewModel();
        mDataBinding.setLifecycleOwner(this);

        init();
        initObserve();
        initListener();

        return mFragmentBaseBinding.getRoot();
    }

    /**
     * 创建ViewModel
     * @param cls         Class
     * @param <T>         Object
     * @param variableId  ViewModel的id，如：BR.viewModel
     * @return            ViewModel
     */
    public <T extends BaseViewModel> T createViewModel(Class<T> cls, int variableId) {
        this.variableId = variableId;
        return new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getActivity().getApplication())).get(cls);
    }

    /**
     * 基础的ViewModel初始化
     */
    private void baseInitViewModel() {
        if(null != mViewModel) {
            // 绑定ViewModel
            mDataBinding.setVariable(variableId, mViewModel);
            // ViewModel订阅生命周期事件
            getLifecycle().addObserver(mViewModel);
            // 添加加载状态 observer
            mViewModel.loadState.observe(getViewLifecycleOwner(), this::addLoadView);
        }
    }

    /**
     * 初始化业务数据以及view视图
     */
    protected void init() {}

    /**
     * 初始化liveData
     */
    protected void initObserve() {}

    /**
     * 初始化(view)相关Listener
     */
    protected void initListener() {}

    /**
     * 处理Intent
     * @param bundle {@link this#getArguments()}
     */
    protected void handleBundle(Bundle bundle) {}

    /**
     * 当前页面的布局资源ID
     * @return    @IdRes
     */
    protected abstract int getLayoutResId();

    /**
     * 初始化ViewModel
     */
    protected void initViewModel() {}

    public BaseFragment<DB, VM> setTag(String tag) {

        return this;
    }


    /**
     * 添加LoadView到视图
     * @param loadState    {@link LoadState}
     */
    private void addLoadView(LoadState loadState) {
        removeLoadView();
        switch (loadState) {
            case LOADING:
                // 注意：此处一定要替换成布局模式，防止activity跳转或调用activity.start()方式导致实例失效DialogHelper显示不正常
                DialogHelper.showProgressDialog(ContractSdk.getInstance().getTopActivity(),"数据加载中").setCanceledOnTouchOutside(loadState.params.isCancelable);
                break;
            case NO_NETWORK:
                addLoadStateViewForLoadState(mViewNoNetworkBinding, R.layout.view_no_network, loadState);
                break;
            case NO_DATA:
                addLoadStateViewForLoadState(mViewNoDataBinding, R.layout.view_no_data, loadState);
                break;
            case ERROR:
                addLoadStateViewForLoadState(mViewLoadErrorBinding, R.layout.view_load_error, loadState);
                break;
            case DIALOG:
                showDialog(loadState);
                break;
            default:
                break;
        }
    }

    /**
     * 公共弹窗
     * fixme:有时间再来优化此处 cyj
     */
    private void showDialog(LoadState loadState) {
        // 当前合同第X页存在印章覆盖\n请重新拖拽！
        RoundDialog.Builder builder = new TagBuilder(getActivity())
                .setTag(loadState.params.tag)
                .title("温馨提示")
                .content(loadState.params.message)
                .contentGravity(Gravity.CENTER)
                .cancelable(false)
                .confirmCallback(this::onDialogOnClick);
        if (!StringUtils.isEmpty(loadState.params.message1)) {
            builder.cancel(loadState.params.message1);
        } else {
            builder.singleBtn(true);
        }

        builder.confirm(!StringUtils.isEmpty(loadState.params.message2) ? loadState.params.message2 : "知道了");
        builder.show();
    }

    protected void onDialogOnClick(View dialogView) {

    }

    /** 移除LoadView */
    private void removeLoadView() {
        int childCount = mFragmentBaseBinding.flContentContainer.getChildCount();
        if (childCount > 1) {
            mFragmentBaseBinding.flContentContainer.removeViews(1, childCount - 1);
        }
    }

    /**
     * 添加LoadState的状态View到业务容器
     * @param obj
     * @param layoutId
     * @param loadState
     */
    private void addLoadStateViewForLoadState(ViewDataBinding obj, int layoutId, LoadState loadState) {
        if(null == loadState.params) {
            return;
        }
        if(null == obj) {
            obj = DataBindingUtil.inflate(getLayoutInflater(), layoutId, mFragmentBaseBinding.flContentContainer, false);
            obj.setVariable(BR.viewModel, mViewModel);
        }
        // 指定原view视图的具体位置来设置覆盖层的属性
        if(loadState.params.left > 0 || loadState.params.top > 0 || loadState.params.right > 0 || loadState.params.bottom > 0) {
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(-1, -1);
            int screenWidth = mFragmentBaseBinding.flContentContainer.getWidth();
            int screenHeight = mFragmentBaseBinding.flContentContainer.getHeight();
            lp.leftMargin = loadState.params.left;
            lp.topMargin = loadState.params.top;
            lp.rightMargin = screenWidth - loadState.params.right;
            lp.bottomMargin = screenHeight - loadState.params.bottom;
            lp.width = loadState.params.right - loadState.params.left;
            lp.height = loadState.params.bottom - loadState.params.top;
            obj.getRoot().setLayoutParams(lp);
        }
        mFragmentBaseBinding.flContentContainer.addView(obj.getRoot());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mViewModel != null) {
            getLifecycle().removeObserver(mViewModel);
        }
        removeLoadView();
    }
}
